package com.hgq.jssjyyxt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hgq.jssjyyxt.entity.Courses;
import com.hgq.jssjyyxt.entity.Trainers;
import com.hgq.jssjyyxt.entity.Users;
import com.hgq.jssjyyxt.mapper.BookingsMapper;
import com.hgq.jssjyyxt.entity.Bookings;
import com.hgq.jssjyyxt.mapper.CoursesMapper;
import com.hgq.jssjyyxt.mapper.TrainersMapper;
import com.hgq.jssjyyxt.mapper.UsersMapper;
import com.hgq.jssjyyxt.service.BookingsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hgq.jssjyyxt.util.Result;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * (Bookings)表服务实现类
 *
 * @author makejava
 * @since 2024-04-11 13:53:35
 */
@Service("bookingsService")
public class BookingsServiceImpl extends ServiceImpl<BookingsMapper, Bookings> implements BookingsService {

    @Autowired
    private CoursesMapper coursesMapper;
    @Autowired
    private TrainersMapper trainersMapper;
    @Autowired
    private UsersMapper usersMapper;

    @Override
    public Result selectAll(Bookings bookings, Integer limit, Integer page) {
        List<Map<String, Object>> list = baseMapper.selectAll(bookings, (page - 1) * limit, limit);
        HashMap<String, Object> result = new HashMap<>();
        result.put("count", baseMapper.selectAllCount(bookings));
        result.put("data", list);
        return Result.success(result);
    }

    @Override
    public Result editState(Bookings bookings) {
        //查询这条预约的数据
        Bookings bookingMain = baseMapper.selectById(bookings.getBookingId());
        //查询这个教练的信息
        Trainers trainersMain = trainersMapper.selectById(bookingMain.getCoachId());
        //查询用户的数据
        Users usersMain = usersMapper.selectById(bookingMain.getUserId());
        //判断这个课程的数据
        Map<String, Object> coursesMain = coursesMapper.getOneById(bookingMain.getCourseId());
        //查询这个课程已经多少人预约成功了这个课程
        Long num = baseMapper.selectCount(new QueryWrapper<Bookings>().eq("course_id", bookingMain.getCourseId()).eq("status", 1));
        //这个课程的最大人数
        Integer maxParticipants = Integer.valueOf(coursesMain.get("maxParticipants").toString());
        //这个课程的价格
        BigDecimal price = new BigDecimal(coursesMain.get("price").toString());
        //获取将要修改成的状态判断   各个状态的条件   1已确认、2待确认、3已取消4、已拒绝
        Integer status = bookings.getStatus();
        //获取原本的状态  只能逐级修改状态
        Integer oldStatus = bookingMain.getStatus();
        if (status == 1) {
            if (oldStatus != 2) {
                return Result.failure("对不起，该状态不能修改");
            }

            if (num >= maxParticipants) {
                return Result.failure("对不起，该课程已满员");
            }

            //判断教练的冻结余额是否大于课程的价格
            if (!this.checkBalance(trainersMain.getFreezeMoney(), price)) {
                return Result.failure("对不起，数据异常！！！");
            }
            //冻结余额加入到余额里面
            Trainers updateTrainers = new Trainers();
            updateTrainers.setTrainerId(trainersMain.getTrainerId());
            updateTrainers.setAccountBalance(trainersMain.getAccountBalance().add(price));
            updateTrainers.setFreezeMoney(trainersMain.getFreezeMoney().subtract(price));
            trainersMapper.updateById(updateTrainers);

            //更新状态
            baseMapper.updateById(bookings);
        } else if (status == 2) {
            //查看是否已经预约了这个课程
            QueryWrapper<Bookings> bookingsQueryWrapper = new QueryWrapper<>();
            bookingsQueryWrapper.eq("course_id", bookings.getCourseId());
            bookingsQueryWrapper.eq("user_id", bookings.getUserId());
            bookingsQueryWrapper.eq("coach_id", bookings.getCoachId());
            bookingsQueryWrapper.or().eq("status", 2).eq("status", 1);
            if (baseMapper.selectCount(bookingsQueryWrapper) > 0){
                return Result.failure("对不起，您已经预约过这个课程");
            }

            if (num >= maxParticipants) {
                return Result.failure("对不起，该课程已满员");
            }

            //判断用户的时间有没有冲突
            List<Bookings> list = baseMapper.findAllByUserIdAndStateAndTime(coursesMain, bookingMain);
            if (list != null && !list.isEmpty()) {
                return Result.failure("对不起，您预约的这个课程时间和您的其他课程时间有冲突，请检查你的课程时间。不能预约！！！");
            }

            //判断用户的余额是否大于课程的价格
            if (!this.checkBalance(usersMain.getAccountBalance(), price)) {
                return Result.failure("对不起，数据异常！！！");
            }

            //扣除用户的余额，加入到教练的动用余额里面
            Users updateUsers = new Users();
            updateUsers.setUserId(usersMain.getUserId());
            updateUsers.setAccountBalance(usersMain.getAccountBalance().subtract(price));
            usersMapper.updateById(updateUsers);
            Trainers updateTrainers = new Trainers();
            updateTrainers.setTrainerId(trainersMain.getTrainerId());
            updateTrainers.setFreezeMoney(trainersMain.getFreezeMoney().add(price));
            trainersMapper.updateById(updateTrainers);

            //更新状态
            baseMapper.updateById(bookings);
        } else if (status == 3) {
            //1、可能已经被教练同意加入了这个课程  2还是待确认状态
            if (oldStatus == 1) {
                //判断是否已经开课coursesMain.getStartTime()跟现在时间作对比，如果已经开课就提示不能取消
                LocalDateTime startTime = (LocalDateTime) coursesMain.get("startTime");
                if (startTime.isBefore(LocalDateTime.now())) {
                    return Result.failure("对不起，该课程已经开课，不能取消！！！");
                }

                //判断教练的余额是否正常
                if (!this.checkBalance(trainersMain.getAccountBalance(), price)) {
                    return Result.failure("对不起，数据异常！！！");
                }

                //还没有开课，可以取消。 扣除教练的余额，加上用户的余额，
                Trainers updateTrainers = new Trainers();
                updateTrainers.setTrainerId(trainersMain.getTrainerId());
                updateTrainers.setAccountBalance(trainersMain.getAccountBalance().subtract(price));
                trainersMapper.updateById(updateTrainers);
                Users updateUsers = new Users();
                updateUsers.setUserId(usersMain.getUserId());
                updateUsers.setAccountBalance(usersMain.getAccountBalance().add(price));
                usersMapper.updateById(updateUsers);
            } else if (oldStatus == 2) {
                //判断教练的冻结余额是否正常
                if (!this.checkBalance(trainersMain.getFreezeMoney(), price)) {
                    return Result.failure("对不起，数据异常！！！");
                }
                //可以直接取消 扣除教练的冻结余额，加上用户的余额，
                Trainers updateTrainers = new Trainers();
                updateTrainers.setTrainerId(trainersMain.getTrainerId());
                updateTrainers.setFreezeMoney(trainersMain.getFreezeMoney().subtract(price));
                trainersMapper.updateById(updateTrainers);
                Users updateUsers = new Users();
                updateUsers.setUserId(usersMain.getUserId());
                updateUsers.setAccountBalance(usersMain.getAccountBalance().add(price));
                usersMapper.updateById(updateUsers);
            } else {
                return Result.failure("对不起，该状态不能修改");
            }
            //更新状态
            baseMapper.updateById(bookings);
        } else if (status == 4) {
            if (oldStatus != 2) {
                return Result.failure("对不起，该状态不能修改");
            }
            if (!this.checkBalance(trainersMain.getFreezeMoney(), price)) {
                return Result.failure("对不起，数据异常！！！");
            }

            //扣除教练的冻结余额，加上用户的余额，
            Trainers updateTrainers = new Trainers();
            updateTrainers.setTrainerId(trainersMain.getTrainerId());
            updateTrainers.setFreezeMoney(trainersMain.getFreezeMoney().subtract(price));
            trainersMapper.updateById(updateTrainers);
            Users updateUsers = new Users();
            updateUsers.setUserId(usersMain.getUserId());
            updateUsers.setAccountBalance(usersMain.getAccountBalance().add(price));
            usersMapper.updateById(updateUsers);
            //更新状态
            baseMapper.updateById(bookings);
        }
        return Result.success("操作成功");
    }

    private boolean checkBalance(BigDecimal freezeMoney, BigDecimal price) {
        return freezeMoney.compareTo(price) >= 0;
    }

    @Override
    public Result saveData(Bookings bookings) {
        //查看是否已经预约了这个课程
        QueryWrapper<Bookings> bookingsQueryWrapper = new QueryWrapper<>();
        bookingsQueryWrapper.eq("course_id", bookings.getCourseId())
                .eq("user_id", bookings.getUserId())
                .eq("coach_id", bookings.getCoachId())
                .and(wrapper -> wrapper.eq("status", 2).or().eq("status", 1));
        if (baseMapper.selectCount(bookingsQueryWrapper) > 0){
            return Result.failure("对不起，您已经预约过这个课程");
        }

        //查询这个教练的信息
        Trainers trainersMain = trainersMapper.selectById(bookings.getCoachId());
        //查询用户的数据
        Users usersMain = usersMapper.selectById(bookings.getUserId());
        //判断这个课程的数据
        Map<String, Object> coursesMain = coursesMapper.getOneById(bookings.getCourseId());
        //查询这个课程已经多少人预约成功了这个课程
        Long num = baseMapper.selectCount(new QueryWrapper<Bookings>().eq("course_id", bookings.getCourseId()).eq("status", 1));
        //这个课程的最大人数
        Integer maxParticipants = Integer.valueOf(coursesMain.get("maxParticipants").toString());
        //这个课程的价格
        BigDecimal price = new BigDecimal(coursesMain.get("price").toString());

        if (num >= maxParticipants) {
            return Result.failure("对不起，该课程已满员");
        }

        //判断用户的时间有没有冲突
        List<Bookings> list = baseMapper.findAllByUserIdAndStateAndTime(coursesMain, bookings);
        if (list != null && !list.isEmpty()) {
            return Result.failure("对不起，您预约的这个课程时间和您的其他课程时间有冲突，请检查你的课程时间。不能预约！！！");
        }

        //判断用户的余额是否大于课程的价格
        if (!this.checkBalance(usersMain.getAccountBalance(), price)) {
            return Result.failure("对不起，数据异常！！！");
        }

        //扣除用户的余额，加入到教练的动用余额里面
        Users updateUsers = new Users();
        updateUsers.setUserId(usersMain.getUserId());
        updateUsers.setAccountBalance(usersMain.getAccountBalance().subtract(price));
        usersMapper.updateById(updateUsers);
        Trainers updateTrainers = new Trainers();
        updateTrainers.setTrainerId(trainersMain.getTrainerId());
        updateTrainers.setFreezeMoney(trainersMain.getFreezeMoney().add(price));
        trainersMapper.updateById(updateTrainers);

        //保存数据
        baseMapper.insert(bookings);
        return Result.success("预约成功");
    }
}

